package util

import (
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"golang.org/x/crypto/bcrypt"
	"mall-admin-go/conf"
	"regexp"
	"strings"
)

// 密码解密
func DecryptPassword(encryptedPassword string) (string, error) {
	key := conf.PasswordKey
	// Base64 解码
	ciphertext, _ := base64.StdEncoding.DecodeString(encryptedPassword)

	block, err := aes.NewCipher([]byte(key))
	if err != nil {
		return "", err
	}

	// 按照 ECB 模式解密
	blockMode := NewECBDecrypter(block)
	plaintext := make([]byte, len(ciphertext))
	blockMode.CryptBlocks(plaintext, ciphertext)

	// 去除 PKCS7 填充
	padding := int(plaintext[len(plaintext)-1])
	plaintext = plaintext[:len(plaintext)-padding]

	return string(plaintext), nil
}

// 余额加密
func EncryptMoney(plaintext string) (string, error) {
	key := []byte(conf.MoneyKey)
	block, err := aes.NewCipher(key)
	if err != nil {
		return "", err
	}

	// 对明文进行填充
	padding := aes.BlockSize - len(plaintext)%aes.BlockSize
	padtext := append([]byte(plaintext), byte(padding))
	for i := 1; i < padding; i++ {
		padtext = append(padtext, byte(0))
	}

	ciphertext := make([]byte, len(padtext))

	blockMode := cipher.NewCBCEncrypter(block, key[:block.BlockSize()])
	blockMode.CryptBlocks(ciphertext, padtext)

	// Base64 编码
	encoded := base64.StdEncoding.EncodeToString(ciphertext)

	return encoded, nil
}

// 余额解密
func DecryptMoney(ciphertext string) (string, error) {
	key := []byte(conf.MoneyKey)
	block, err := aes.NewCipher(key)
	if err != nil {
		return "", err
	}

	// Base64 解码
	decoded, err := base64.StdEncoding.DecodeString(ciphertext)
	if err != nil {
		return "", err
	}

	plaintext := make([]byte, len(decoded))

	blockMode := cipher.NewCBCDecrypter(block, key[:block.BlockSize()])
	blockMode.CryptBlocks(plaintext, decoded)

	// 去除填充
	padding := int(plaintext[len(plaintext)-1])
	plaintext = plaintext[:len(plaintext)-padding]

	money := string(plaintext)
	re := regexp.MustCompile(`[\s\n]+`)
	str := re.ReplaceAllString(money, "")
	result := strings.ReplaceAll(str, "\u0000", "")
	result1 := strings.ReplaceAll(result, "\u000e", "")

	return result1, nil
}

func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
	return &ecbDecrypter{b: b}
}

type ecbDecrypter struct {
	b         cipher.Block
	blockSize int
}

// BlockSize 这下面的不管
func (x *ecbDecrypter) BlockSize() int { return x.b.BlockSize() }

func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
	if len(src)%x.b.BlockSize() != 0 {
		panic("crypto/ecb: input not full blocks")
	}
	if len(dst) < len(src) {
		panic("crypto/ecb: output smaller than input")
	}

	for len(src) > 0 {
		x.b.Decrypt(dst, src[:x.b.BlockSize()])
		src = src[x.b.BlockSize():]
		dst = dst[x.b.BlockSize():]
	}
}

// 生成密码
func GenPwd(pwd string) ([]byte, error) {
	hash, err := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost) //加密处理
	return hash, err
}
